package fcrypt

import (
	"crypto/rand"
	"fmt"
	"math/big"
	"strings"
)

//仿射密码，根据公式 cipher = ((plain * k1)%m + k2)%m得到密文
//k1是乘数加密的密钥
//k2是caser加密的密钥
//m是一个域空间

var AffineSpace = "abcdefghijklmnopqrstuvwxyz"

func AffineGetKey() int {
	keySpace := len(AffineSpace)
	key1 := 0
	key2 := 0
	key1Max := big.NewInt(int64(keySpace - 2))
	for true {
		t, _ := rand.Int(rand.Reader, key1Max)
		key1 = int(t.Int64() + 2)
		if (key1 != 0) && (Gcd(key1, keySpace) == 1) {
			break
		}
	}
	t, _ := rand.Int(rand.Reader, key1Max)
	key2 = int(t.Int64())
	key := key1*26 + key2
	fmt.Printf("密钥 = %d\n", key)
	return key
}

func AffineEnc(plain string, key int) string {
	plainLower := strings.ToLower(plain)
	plainByte := []byte(plainLower)
	plainLen := len(plainByte)
	cipherByte := make([]byte, plainLen, plainLen)

	keySpace := len(AffineSpace)
	key1 := key / keySpace
	key2 := key % keySpace
	fmt.Printf("密钥 key1 = %d, key2 = %d\n", key1, key2)
	for i := 0; i < plainLen; i++ {
		v := int(plainByte[i] - 97)
		v = v * key1 % 26
		v = (v + key2) % 26
		v = v + 97
		cipherByte[i] = byte(v)
	}
	cipher := string(cipherByte)
	return cipher
}

func AffineDec(cipher string, key int) string {
	cipherByte := []byte(cipher)
	cipherLen := len(cipherByte)
	plainByte := make([]byte, cipherLen, cipherLen)

	keySpace := len(AffineSpace)
	key1 := key / keySpace
	key2 := key % keySpace
	decKey := GetModInverse(key1, keySpace)
	fmt.Printf("密钥 decKey = %d, key2 = %d\n", decKey, key2)
	for i := 0; i < cipherLen; i++ {
		v := int(cipherByte[i] - 97)
		v = (v - key2 + 26) % 26
		v = v * decKey % 26
		v = v + 97
		plainByte[i] = byte(v)
	}
	plain := string(plainByte)
	return plain
}
